package com.thanos.api.blockchain;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * BlockchainController.java description：Thanos链区块链SDK接口控制器
 *
 * @Author create on 2024-12-19
 */
@RestController
@RequestMapping("/api/blockchain")
@CrossOrigin(origins = "*")
public class BlockchainController {
    
    private static final Logger logger = LoggerFactory.getLogger(BlockchainController.class);
    
    @Autowired
    private BlockchainService blockchainService;
    
    /**
     * 获取目前最新被异步执行的区块块高
     */
    @GetMapping("/latest-executed-number")
    public ResponseEntity<Map<String, Object>> getLatestBeExecutedNum() {
        try {
            Long blockNumber = blockchainService.getLatestBeExecutedNum();
            Map<String, Object> response = new HashMap<>();
            response.put("success", true);
            response.put("blockNumber", blockNumber);
            response.put("message", "Successfully retrieved latest executed block number");
            return ResponseEntity.ok(response);
        } catch (Exception e) {
            logger.error("Error getting latest executed block number: {}", e.getMessage(), e);
            Map<String, Object> errorResponse = new HashMap<>();
            errorResponse.put("success", false);
            errorResponse.put("error", e.getMessage());
            return ResponseEntity.status(500).body(errorResponse);
        }
    }
    
    /**
     * 获取目前最新被异步共识的区块块高
     */
    @GetMapping("/latest-consensus-number")
    public ResponseEntity<Map<String, Object>> getLatestConsensusNumber() {
        try {
            Long blockNumber = blockchainService.getLatestConsensusNumber();
            Map<String, Object> response = new HashMap<>();
            response.put("success", true);
            response.put("blockNumber", blockNumber);
            response.put("message", "Successfully retrieved latest consensus block number");
            return ResponseEntity.ok(response);
        } catch (Exception e) {
            logger.error("Error getting latest consensus block number: {}", e.getMessage(), e);
            Map<String, Object> errorResponse = new HashMap<>();
            errorResponse.put("success", false);
            errorResponse.put("error", e.getMessage());
            return ResponseEntity.status(500).body(errorResponse);
        }
    }
    
    /**
     * 获取目前最新的共识轮次
     */
    @GetMapping("/current-commit-round")
    public ResponseEntity<Map<String, Object>> getCurrentCommitRound() {
        try {
            Long round = blockchainService.getCurrentCommitRound();
            Map<String, Object> response = new HashMap<>();
            response.put("success", true);
            response.put("round", round);
            response.put("message", "Successfully retrieved current commit round");
            return ResponseEntity.ok(response);
        } catch (Exception e) {
            logger.error("Error getting current commit round: {}", e.getMessage(), e);
            Map<String, Object> errorResponse = new HashMap<>();
            errorResponse.put("success", false);
            errorResponse.put("error", e.getMessage());
            return ResponseEntity.status(500).body(errorResponse);
        }
    }
    
    /**
     * 通过blockNumber获取区块链信息
     */
    @GetMapping("/block/{blockNumber}")
    public ResponseEntity<Map<String, Object>> getBlockByNumber(@PathVariable String blockNumber) {
        try {
            String blockInfo = blockchainService.getBlockByNumber(blockNumber);
            Map<String, Object> response = new HashMap<>();
            response.put("success", true);
            response.put("blockNumber", blockNumber);
            response.put("blockInfo", blockInfo);
            response.put("message", "Successfully retrieved block information");
            return ResponseEntity.ok(response);
        } catch (Exception e) {
            logger.error("Error getting block by number {}: {}", blockNumber, e.getMessage(), e);
            Map<String, Object> errorResponse = new HashMap<>();
            errorResponse.put("success", false);
            errorResponse.put("error", e.getMessage());
            return ResponseEntity.status(500).body(errorResponse);
        }
    }
    
    /**
     * 通过交易hash获取交易信息（网关缓存）
     */
    @GetMapping("/transaction/{transactionHash}")
    public ResponseEntity<Map<String, Object>> getEthTransactionByHash(@PathVariable String transactionHash) {
        try {
            String transactionInfo = blockchainService.getEthTransactionByHash(transactionHash);
            Map<String, Object> response = new HashMap<>();
            response.put("success", true);
            response.put("transactionHash", transactionHash);
            response.put("transactionInfo", transactionInfo);
            response.put("message", "Successfully retrieved transaction information from gateway cache");
            return ResponseEntity.ok(response);
        } catch (Exception e) {
            logger.error("Error getting transaction by hash {}: {}", transactionHash, e.getMessage(), e);
            Map<String, Object> errorResponse = new HashMap<>();
            errorResponse.put("success", false);
            errorResponse.put("error", e.getMessage());
            return ResponseEntity.status(500).body(errorResponse);
        }
    }
    
    /**
     * 通过交易hash获取交易信息（全量历史）
     */
    @GetMapping("/transaction-by-chain/{transactionHash}")
    public ResponseEntity<Map<String, Object>> getEthTransactionByHashByChain(@PathVariable String transactionHash) {
        try {
            String transactionInfo = blockchainService.getEthTransactionByHashByChain(transactionHash);
            Map<String, Object> response = new HashMap<>();
            response.put("success", true);
            response.put("transactionHash", transactionHash);
            response.put("transactionInfo", transactionInfo);
            response.put("message", "Successfully retrieved transaction information from full history");
            return ResponseEntity.ok(response);
        } catch (Exception e) {
            logger.error("Error getting transaction by hash from chain {}: {}", transactionHash, e.getMessage(), e);
            Map<String, Object> errorResponse = new HashMap<>();
            errorResponse.put("success", false);
            errorResponse.put("error", e.getMessage());
            return ResponseEntity.status(500).body(errorResponse);
        }
    }
    
    /**
     * 通过交易hash批量获取交易信息
     */
    @PostMapping("/transactions-by-hashes")
    public ResponseEntity<Map<String, Object>> getEthTransactionsByHashes(@RequestBody Map<String, List<String>> request) {
        try {
            List<String> transactionHashList = request.get("transactionHashList");
            if (transactionHashList == null || transactionHashList.isEmpty()) {
                Map<String, Object> errorResponse = new HashMap<>();
                errorResponse.put("success", false);
                errorResponse.put("error", "Transaction hash list cannot be null or empty");
                return ResponseEntity.badRequest().body(errorResponse);
            }
            
            List<String> transactionInfo = blockchainService.getEthTransactionsByHashes(transactionHashList);
            Map<String, Object> response = new HashMap<>();
            response.put("success", true);
            response.put("transactionHashList", transactionHashList);
            response.put("transactionInfo", transactionInfo);
            response.put("message", "Successfully retrieved batch transaction information");
            return ResponseEntity.ok(response);
        } catch (Exception e) {
            logger.error("Error getting transactions by hashes: {}", e.getMessage(), e);
            Map<String, Object> errorResponse = new HashMap<>();
            errorResponse.put("success", false);
            errorResponse.put("error", e.getMessage());
            return ResponseEntity.status(500).body(errorResponse);
        }
    }
    
    /**
     * 通过全局节点事件hash获取事件信息（网关缓存）
     */
    @GetMapping("/global-node-event/{eventHash}")
    public ResponseEntity<Map<String, Object>> getGlobalNodeEventByHash(@PathVariable String eventHash) {
        try {
            String eventInfo = blockchainService.getGlobalNodeEventByHash(eventHash);
            Map<String, Object> response = new HashMap<>();
            response.put("success", true);
            response.put("eventHash", eventHash);
            response.put("eventInfo", eventInfo);
            response.put("message", "Successfully retrieved global node event information from gateway cache");
            return ResponseEntity.ok(response);
        } catch (Exception e) {
            logger.error("Error getting global node event by hash {}: {}", eventHash, e.getMessage(), e);
            Map<String, Object> errorResponse = new HashMap<>();
            errorResponse.put("success", false);
            errorResponse.put("error", e.getMessage());
            return ResponseEntity.status(500).body(errorResponse);
        }
    }
    
    /**
     * 通过全局节点事件hash获取事件信息（全量历史）
     */
    @GetMapping("/global-node-event-by-chain/{eventHash}")
    public ResponseEntity<Map<String, Object>> getGlobalNodeEventByHashByChain(@PathVariable String eventHash) {
        try {
            String eventInfo = blockchainService.getGlobalNodeEventByHashByChain(eventHash);
            Map<String, Object> response = new HashMap<>();
            response.put("success", true);
            response.put("eventHash", eventHash);
            response.put("eventInfo", eventInfo);
            response.put("message", "Successfully retrieved global node event information from full history");
            return ResponseEntity.ok(response);
        } catch (Exception e) {
            logger.error("Error getting global node event by hash from chain {}: {}", eventHash, e.getMessage(), e);
            Map<String, Object> errorResponse = new HashMap<>();
            errorResponse.put("success", false);
            errorResponse.put("error", e.getMessage());
            return ResponseEntity.status(500).body(errorResponse);
        }
    }
    
    /**
     * 通过全局节点事件hash获取事件回执
     */
    @GetMapping("/global-node-event-receipt/{eventHash}")
    public ResponseEntity<Map<String, Object>> getGlobalNodeEventReceiptByHash(@PathVariable String eventHash) {
        try {
            String eventReceipt = blockchainService.getGlobalNodeEventReceiptByHash(eventHash);
            Map<String, Object> response = new HashMap<>();
            response.put("success", true);
            response.put("eventHash", eventHash);
            response.put("eventReceipt", eventReceipt);
            response.put("message", "Successfully retrieved global node event receipt");
            return ResponseEntity.ok(response);
        } catch (Exception e) {
            logger.error("Error getting global node event receipt by hash {}: {}", eventHash, e.getMessage(), e);
            Map<String, Object> errorResponse = new HashMap<>();
            errorResponse.put("success", false);
            errorResponse.put("error", e.getMessage());
            return ResponseEntity.status(500).body(errorResponse);
        }
    }
    
    /**
     * 发送交易请求到区块链立即执行，无需共识
     */
    @PostMapping("/eth-call")
    public ResponseEntity<Map<String, Object>> ethCall(@RequestBody Map<String, String> request) {
        try {
            String rawData = request.get("rawData");
            if (rawData == null || rawData.trim().isEmpty()) {
                Map<String, Object> errorResponse = new HashMap<>();
                errorResponse.put("success", false);
                errorResponse.put("error", "Raw data cannot be null or empty");
                return ResponseEntity.badRequest().body(errorResponse);
            }
            
            String receipt = blockchainService.ethCall(rawData);
            Map<String, Object> response = new HashMap<>();
            response.put("success", true);
            response.put("rawData", rawData);
            response.put("receipt", receipt);
            response.put("message", "Successfully executed eth call");
            return ResponseEntity.ok(response);
        } catch (Exception e) {
            logger.error("Error executing eth call: {}", e.getMessage(), e);
            Map<String, Object> errorResponse = new HashMap<>();
            errorResponse.put("success", false);
            errorResponse.put("error", e.getMessage());
            return ResponseEntity.status(500).body(errorResponse);
        }
    }
    
    /**
     * 发送全局节点事件请求到区块链执行，返回事件hash
     */
    @PostMapping("/send-global-node-event")
    public ResponseEntity<Map<String, Object>> sendGlobalNodeEvent(@RequestBody Map<String, String> request) {
        try {
            String rawData = request.get("rawData");
            if (rawData == null || rawData.trim().isEmpty()) {
                Map<String, Object> errorResponse = new HashMap<>();
                errorResponse.put("success", false);
                errorResponse.put("error", "Raw data cannot be null or empty");
                return ResponseEntity.badRequest().body(errorResponse);
            }
            
            String eventHash = blockchainService.sendGlobalNodeEvent(rawData);
            Map<String, Object> response = new HashMap<>();
            response.put("success", true);
            response.put("rawData", rawData);
            response.put("eventHash", eventHash);
            response.put("message", "Successfully sent global node event");
            return ResponseEntity.ok(response);
        } catch (Exception e) {
            logger.error("Error sending global node event: {}", e.getMessage(), e);
            Map<String, Object> errorResponse = new HashMap<>();
            errorResponse.put("success", false);
            errorResponse.put("error", e.getMessage());
            return ResponseEntity.status(500).body(errorResponse);
        }
    }
    
    /**
     * 发送交易请求到区块链执行，返回交易hash
     */
    @PostMapping("/send-raw-transaction")
    public ResponseEntity<Map<String, Object>> sendEthRawTransaction(@RequestBody Map<String, String> request) {
        try {
            String rawData = request.get("rawData");
            if (rawData == null || rawData.trim().isEmpty()) {
                Map<String, Object> errorResponse = new HashMap<>();
                errorResponse.put("success", false);
                errorResponse.put("error", "Raw data cannot be null or empty");
                return ResponseEntity.badRequest().body(errorResponse);
            }
            
            String transactionHash = blockchainService.sendEthRawTransaction(rawData);
            Map<String, Object> response = new HashMap<>();
            response.put("success", true);
            response.put("rawData", rawData);
            response.put("transactionHash", transactionHash);
            response.put("message", "Successfully sent raw transaction");
            return ResponseEntity.ok(response);
        } catch (Exception e) {
            logger.error("Error sending raw transaction: {}", e.getMessage(), e);
            Map<String, Object> errorResponse = new HashMap<>();
            errorResponse.put("success", false);
            errorResponse.put("error", e.getMessage());
            return ResponseEntity.status(500).body(errorResponse);
        }
    }
    
    /**
     * 批量发送交易请求到区块链执行，返回交易hash列表
     */
    @PostMapping("/send-raw-transaction-list")
    public ResponseEntity<Map<String, Object>> sendEthRawTransactionList(@RequestBody Map<String, List<String>> request) {
        try {
            List<String> rawDataList = request.get("rawDataList");
            if (rawDataList == null || rawDataList.isEmpty()) {
                Map<String, Object> errorResponse = new HashMap<>();
                errorResponse.put("success", false);
                errorResponse.put("error", "Raw data list cannot be null or empty");
                return ResponseEntity.badRequest().body(errorResponse);
            }
            
            List<String> transactionHashList = blockchainService.sendEthRawTransactionList(rawDataList);
            Map<String, Object> response = new HashMap<>();
            response.put("success", true);
            response.put("rawDataList", rawDataList);
            response.put("transactionHashList", transactionHashList);
            response.put("message", "Successfully sent batch raw transactions");
            return ResponseEntity.ok(response);
        } catch (Exception e) {
            logger.error("Error sending raw transaction list: {}", e.getMessage(), e);
            Map<String, Object> errorResponse = new HashMap<>();
            errorResponse.put("success", false);
            errorResponse.put("error", e.getMessage());
            return ResponseEntity.status(500).body(errorResponse);
        }
    }
}